package com.smartstate.IOC.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.smartstate.IOC.dto.PageDTO;
import com.smartstate.IOC.entity.DeviceCarePlan;
import com.smartstate.IOC.entity.EquipMent;
import com.smartstate.IOC.mapper.CarbonConfigMapper;
import com.smartstate.IOC.mapper.EquipmentMapper;
import com.smartstate.IOC.service.EquipmentService;
import com.smartstate.IOC.vo.EquipMentVidioVo;
import com.smartstate.IOC.vo.MoudelEquipmentVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class EquipmentServiceImpl extends ServiceImpl<EquipmentMapper, EquipMent> implements EquipmentService {

    /**
     * 环境监控设备id集
     */
    static final List<String> ENVIRONMENT_EQUIPMENT_SET = Lists.newArrayList("1");
    /**
     * 视频监控设备id集
     */
    static final List<String> MONITOR_EQUIPMENT_SET = Lists.newArrayList("18");
    /**
     * 工业自控设备id集
     */
    static final List<String> CONTROL_EQUIPMENT_SET = Lists.newArrayList("6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17");
    /**
     * 电表设备id集
     */
    static final List<String> ELECTRICITY_METER_SET = Lists.newArrayList("2");

    static final Long DAY_TIME_MILLS = 24 * 60 * 60 * 1000L;

    static final List<String> ALL_TYPE_SET = Lists.newArrayList();

    {
        ALL_TYPE_SET.addAll(ENVIRONMENT_EQUIPMENT_SET);
        ALL_TYPE_SET.addAll(MONITOR_EQUIPMENT_SET);
        ALL_TYPE_SET.addAll(CONTROL_EQUIPMENT_SET);
        ALL_TYPE_SET.addAll(ELECTRICITY_METER_SET);
    }


    static final String EQUIPMENT_TYPE_ELECTRICITY_METER = "2";
    static final String EQUIPMENT_ENABLE_TYPE_ONLINE = "在线";
    static final String EQUIPMENT_ENABLE_TYPE_OFFLINE = "离线";

    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public Page<EquipMent> queryAllPageByDTO(PageDTO pageDTO) {
        return null;
    }

    public Map<String, Map<String, Object>> getOnlineStateEquipmets() {
        MoudelEquipmentVo rootNode = getMoudelEquipmentTree("1");

        //<楼栋名称，<在线/离线， 数量>>
        Map<String, Map<String, Object>> result = new HashMap<>();
        for (MoudelEquipmentVo buildingMoudel : rootNode.getSubMoudels()) {
            //获取指定模块及该模块所有下级的设备
            List<MoudelEquipmentVo> moudels = getTargetSubMoudels(buildingMoudel);
             moudels = moudels.stream().filter(e -> StringUtils.isNotBlank(e.getDeviceId()) && EQUIPMENT_TYPE_ELECTRICITY_METER.equals(e.getEquipmentType())).collect(Collectors.toList());
             if(CollectionUtils.isEmpty(moudels)){
                continue;
             }
             for(MoudelEquipmentVo me : moudels){
                 Object deviceOnlineState = redisTemplate.opsForHash().get(me.getDeviceId(),"type");
                 String enableType = deviceOnlineState == null ? EQUIPMENT_ENABLE_TYPE_OFFLINE : EQUIPMENT_ENABLE_TYPE_OFFLINE.equals(deviceOnlineState) ? EQUIPMENT_ENABLE_TYPE_OFFLINE : EQUIPMENT_ENABLE_TYPE_ONLINE;
                 me.setEnabledType(enableType);
             }
             Map<String, Object> innerResult = new HashMap<>();
            innerResult.put(EQUIPMENT_ENABLE_TYPE_OFFLINE, moudels.stream().filter(e -> EQUIPMENT_ENABLE_TYPE_OFFLINE.equals(e.getEnabledType())).collect(Collectors.toList()).size());
            innerResult.put(EQUIPMENT_ENABLE_TYPE_ONLINE, moudels.stream().filter(e -> EQUIPMENT_ENABLE_TYPE_ONLINE.equals(e.getEnabledType())).collect(Collectors.toList()).size());
            result.put(buildingMoudel.getMoudelName(), innerResult);
        }
        return result;
    }

    public List<Map<String, Object>> getTeamCountInfos() {
        return baseMapper.getTeamCountInfos();
    }

    /**
     * 查询设备类型为摄像头数量
     */
    @Override
    public Map<String, Integer> getDeviceVidio() {
        Integer device = baseMapper.getDeviceVidio();
        HashMap<String, Integer> stringHashMap = new HashMap<>();
        stringHashMap.put("尘埃粒子5.0",device);
        stringHashMap.put("尘埃粒子0.5",device);
        stringHashMap.put("露点传感器",device);
        stringHashMap.put("温度传感器",device);
        stringHashMap.put("湿度传感器",device);
        stringHashMap.put("静压传感器",device);
        return stringHashMap;
    }

    public List<DeviceCarePlan> getEquipmentCarePlans() {
        List<DeviceCarePlan> planRecs = baseMapper.getEquipmentCarePlans();
        final Long currTime = new Date().getTime();
        planRecs.stream().forEach(e -> {
            String careMsg = "";
            Long toCareTime = e.getCareTime().getTime() - currTime;
            if (toCareTime < DAY_TIME_MILLS) {
                careMsg = "请于今天完成保养";
            } else {
                int a = (int) Math.floor(toCareTime / DAY_TIME_MILLS);
                careMsg = String.valueOf(a);
            }
            e.setCareMsg(careMsg);
        });
        return planRecs;
    }


    /**
     * 获取园区所有设备的模块树
     *
     * @return
     */
    public MoudelEquipmentVo getMoudelEquipmentTree(String type) {
        List<MoudelEquipmentVo> reslut = baseMapper.getMoudels(type);
        MoudelEquipmentVo rootNode = reslut.stream().filter(e -> StringUtils.isEmpty(e.getMoudelParentId()) || "0".equals(e.getMoudelParentId())).collect(Collectors.toList()).get(0);
        //用所有模块设备记录数据构建 模块设备树
        constructSubMoudels(rootNode, reslut);
        return rootNode;
    }


    @Override
    public Map<String, Integer> getMoudelEquipments() throws Exception {
        MoudelEquipmentVo rootNode = getMoudelEquipmentTree("1");
        //构建对应模块设备种类统计数量集合
        Map<String, Integer> moudelEquipmentTypeMap = new HashMap<>();
        //获取指定模块及该模块所有下级的设备
        List<MoudelEquipmentVo> tempList = getTargetSubMoudels(rootNode);
        //根据设备类型将指定模块及该模块所有下级的设备分组统计
        if (CollectionUtils.isEmpty(tempList)) {
            return moudelEquipmentTypeMap;
        }
        tempList = tempList.stream().filter(e -> StringUtils.isNotBlank(e.getEquipmentType()) && ALL_TYPE_SET.contains(e.getEquipmentType())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(tempList)) {
            return moudelEquipmentTypeMap;
        }

        moudelEquipmentTypeMap.put("total", tempList.size());
        moudelEquipmentTypeMap.put("环境监控设备", tempList.stream().filter(e -> ENVIRONMENT_EQUIPMENT_SET.contains(e.getEquipmentType())).collect(Collectors.toList()).size());
        moudelEquipmentTypeMap.put("视频监控设备", tempList.stream().filter(e -> MONITOR_EQUIPMENT_SET.contains(e.getEquipmentType())).collect(Collectors.toList()).size());
        moudelEquipmentTypeMap.put("工业自控设备", tempList.stream().filter(e -> CONTROL_EQUIPMENT_SET.contains(e.getEquipmentType())).collect(Collectors.toList()).size());
        moudelEquipmentTypeMap.put("电量抄表设备", tempList.stream().filter(e -> ELECTRICITY_METER_SET.contains(e.getEquipmentType())).collect(Collectors.toList()).size());

        return moudelEquipmentTypeMap;
    }



    public void getTargetMoudles(List<MoudelEquipmentVo> originalEquipments, MoudelEquipmentVo targetModule){
        //无设备ID，且无子模块跳过该模块
        if (StringUtils.isBlank(targetModule.getMoudelId()) && CollectionUtils.isEmpty(targetModule.getSubMoudels())) {
            return;
        }

        //若该记录设备ID 不为空说明改模块存在设备
        if (StringUtils.isNotBlank(targetModule.getMoudelId())) {
            originalEquipments.add(targetModule);
        }

        //存在子模块递归获取子模块设备
        if (CollectionUtils.isNotEmpty(targetModule.getSubMoudels())) {
            for (MoudelEquipmentVo subMoudel : targetModule.getSubMoudels()) {
                getTargetMoudles(originalEquipments, subMoudel);
            }
        }
    }


    /**
     * 获取指定模块及该模块所有下级的设备
     * @param targetModule       本次统计的目标模块
     */
    public List<MoudelEquipmentVo> getTargetSubMoudels( MoudelEquipmentVo targetModule) {
        List<MoudelEquipmentVo> targetSubModels = new ArrayList<>();
        getTargetMoudles(targetSubModels, targetModule);
        List<String> targetObjIds = targetSubModels.stream().map(MoudelEquipmentVo :: getMoudelId).collect(Collectors.toList());
        List<MoudelEquipmentVo> targetMoudels = baseMapper.getMoudelEquipments(targetModule.getObjType(), targetObjIds);
        targetMoudels = targetMoudels.stream().filter(e ->  StringUtils.isNotBlank(e.getDeviceId())).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(targetMoudels)){
            return targetMoudels;
        }
        return new ArrayList<>();
    }

    /**
     * 将模块设备信息构建到主模块下，形成树型结构
     *
     * @param root
     * @param reslut
     */
    public void constructSubMoudels(MoudelEquipmentVo root, List<MoudelEquipmentVo> reslut) {
        if (CollectionUtils.isEmpty(reslut)) {
            return;
        }
        List<MoudelEquipmentVo> subNods = new ArrayList<>();
        Iterator<MoudelEquipmentVo> iterators = reslut.iterator();
        while (iterators.hasNext()) {
            MoudelEquipmentVo moudelEquipmentVo = iterators.next();
            if (root.getMoudelId().equals(moudelEquipmentVo.getMoudelParentId())) {
                subNods.add(moudelEquipmentVo);
                iterators.remove();
            }
        }
        if (CollectionUtils.isNotEmpty(subNods)) {
            root.setSubMoudels(subNods);
            subNods.stream().forEach(e -> constructSubMoudels(e, reslut));
        }
    }

    /**
     * 获取指定模型下的总数量
     *
     * @param targetMoudel
     * @return
     */
    public Integer countEquipmentNums(MoudelEquipmentVo targetMoudel) {

        List<MoudelEquipmentVo> moudelsEquipments = targetMoudel.getSubMoudels();
        if (CollectionUtils.isEmpty(moudelsEquipments)) {
            return 0;
        }

        List<MoudelEquipmentVo> moudelWhithEquipments = moudelsEquipments.stream().filter(e -> StringUtils.isNotBlank(e.getDeviceId()) || CollectionUtils.isNotEmpty(e.getSubMoudels())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(moudelWhithEquipments)) {
            return 0;
        }
        int count = 0;
        for (MoudelEquipmentVo vo : moudelWhithEquipments) {
            if (StringUtils.isNotBlank(vo.getDeviceId())) {
                count++;
            }
            if (CollectionUtils.isNotEmpty(vo.getSubMoudels())) {
                count += countEquipmentNums(vo);
            }
        }
        return count;
    }


    /**
     * 查询今日设备离线统计
     *
     * @return
     */
    @Override
    public Map<String, List<Integer>> getDeviceObj() {
        HashMap<String, List<Integer>> stringListHashMap = new HashMap<>();
        // 获取园区所有设备的模块树
        MoudelEquipmentVo moudelEquipmentTree = getMoudelEquipmentTree("1");
        // 获取树的本模块子模块
        List<MoudelEquipmentVo> subMoudels = moudelEquipmentTree.getSubMoudels();
        //所有的楼栋名称
        for (MoudelEquipmentVo subMoudel : subMoudels) {
            // 统计出
            ArrayList<Integer> integers = new ArrayList<>();
            int i = 0;
            int o = 0;
            List<MoudelEquipmentVo> originalEquipments = new ArrayList<>();
            // 获取指定模块及该模块所有下级的设备
            originalEquipments.addAll(getTargetSubMoudels(subMoudel));
            List<MoudelEquipmentVo> vos = originalEquipments.stream().filter(e -> StringUtils.isNotBlank(e.getDeviceId())).collect(Collectors.toList());
            for (MoudelEquipmentVo vo : vos) {
                Object type = redisTemplate.opsForHash().get(vo.getDeviceId(), "type");
                if ("0".equals(type)) {
                    vo.setEnabledType("在线");
                    i = i + 1;
                } else {
                    vo.setEnabledType("离线");
                    o = o + 1;
                }
            }
            integers.add(o);
            integers.add(i);
            vos.stream().collect(Collectors.groupingBy(MoudelEquipmentVo::getEnabledType, Collectors.counting()));
            stringListHashMap.put(subMoudel.getMoudelName(),integers);
        }
        System.out.println(stringListHashMap);
        return stringListHashMap;
    }

    @Override
    public List<EquipMentVidioVo> getDeviceVidioTotal() {
        List<EquipMent> deviceVidioTotal = baseMapper.getDeviceVidioTotal();
        ArrayList<EquipMentVidioVo> equipMentVidioVos = new ArrayList<>();
        for (EquipMent equipMent : deviceVidioTotal) {
            EquipMentVidioVo equipMentVidioVo = new EquipMentVidioVo();
            equipMentVidioVo.setDeviceId(equipMent.getDeviceId());
            equipMentVidioVo.setDeviceName(equipMent.getName());
            equipMentVidioVos.add(equipMentVidioVo);
        }
        return equipMentVidioVos;
    }

    @Autowired
    CarbonConfigMapper carbonConfigMapper;

    @Override
    public Map<String, Object> getVidioEquipment(EquipMent equipMent) {
        //根据设备id去redis中查询设备参数
        Map entries = redisTemplate.opsForHash().entries(equipMent.getDeviceId());
        // 各个环境值
        HashMap<String, Object> stringIntegerHashMap = new HashMap<>();
        if (entries.get("dewPoint") != null){
            stringIntegerHashMap.put("露点",entries.get("dewPoint"));
        }else {
            stringIntegerHashMap.put("露点","0.0");
        }
        if (entries.get("temperature") != null){
            stringIntegerHashMap.put("温度",entries.get("temperature"));
        }else {
            stringIntegerHashMap.put("温度","0.0");
        }
        if (entries.get("humidity") != null){
            stringIntegerHashMap.put("湿度",entries.get("humidity"));
        }else {
            stringIntegerHashMap.put("湿度","0.0");
        }
        if (entries.get("staticPressure") != null){
            stringIntegerHashMap.put("静压",entries.get("staticPressure"));
        }else {
            stringIntegerHashMap.put("静压","0.0");
        }
        if (entries.get("longParticle") != null){
            stringIntegerHashMap.put("0.5",entries.get("longParticle"));
        }else {
            stringIntegerHashMap.put("0.5","0.0");
        }
        if (entries.get("littleParticle") != null){
            stringIntegerHashMap.put("5.0",entries.get("littleParticle"));
        }else {
            stringIntegerHashMap.put("5.0","0.0");
        }
        return stringIntegerHashMap;
    }

    private static String url = "http://10.98.2.1:7086/live/cameraid/{channelId}%243/substream/1.m3u8";

    public Map<String, String> getCameraChannelUrls(){
        List<EquipMent> all = baseMapper.findAll();
        Map<String, String> result = new HashMap<>();
        for(EquipMent e : all){
            String channelId = getChannelId(e.getAdditionalAttribute());
            String deviceId = e.getDeviceId();
            if(StringUtils.isBlank(channelId)){
                log.info("======getCameraChannelUrls======未获取设备：{}对应视频ChannelUrl出现问题 ", deviceId);
                continue;
            }
            result.put(e.getDeviceId(), url.replace("{channelId}", channelId));
        }
        return result;
    }
    public String getChannelUrlByCameraId(String cameraId) {
        EquipMent equipMent = baseMapper.getChannelIdByCameraId(cameraId);
        if(equipMent == null){
            return null;
        }
        String channelId = getChannelId(equipMent.getAdditionalAttribute());
        if(StringUtils.isBlank(channelId)){
            return null;
        }
        return url.replace("{channelId}", channelId);
    }

    /**
     * 查询环境设备总数
     * @return
     */
    @Override
    public Map<String, Integer> getAlarmEvent() {
        Integer alarmEvent = baseMapper.getAlarmEvent();
        HashMap<String, Integer> stringIntegerHashMap = new HashMap<>();
        stringIntegerHashMap.put("露点传感器",alarmEvent);
        stringIntegerHashMap.put("温度传感器",alarmEvent);
        stringIntegerHashMap.put("湿度传感器",alarmEvent);
        stringIntegerHashMap.put("静压传感器",alarmEvent);
        stringIntegerHashMap.put("尘埃粒子0.5",alarmEvent);
        stringIntegerHashMap.put("尘埃粒子5.0",alarmEvent);
        return stringIntegerHashMap;
    }

    @Override
    public Map<String, Integer> getDeviceVideo() {
        HashMap<String, Integer> maps = new HashMap<>();
        maps.put("枪式摄像机",699);
        maps.put("半球式摄像机",9);
        maps.put("室外独立保护罩摄像机",82);
        maps.put("市内半球式摄像机",68);
        maps.put("高清红外球形摄像机",4);
        return maps;
    }

    private String getChannelId(String jsonStr){
        List<Map> jsonInfos = JSON.parseArray(jsonStr, Map.class);
        String channelId = null;
        for(Map jsonInfo: jsonInfos){
            if (jsonInfo.containsKey("accessId")){
                channelId = String.valueOf(jsonInfo.get("accessId"));
                break;
            }
        }
        return channelId;
    }

}